#!/usr/bin/env python2.6
# -*- coding: utf-8 -*-
""" Bootloader interface: macros y funciones del bootloader usb compartidos
    entre el firmware del bootloader del dispositivo y el software de aplicación.
    (Definido en USB_BL_Interface.h)
"""
import ctypes as c

## Constantes globlales
INVALID_HANDLE_VALUE = 0

## Bootloader Serial String Last Character
## Used by the application and bootloader PC software to determine if a
## USBXpress device is in bootload mode. 
BL_MODE_SERIAL_STR_LAST_CHAR='~'

## Bootloader Commands
CMD_GET_DEVICE_INFO = 0x00  # "Get Device Info" Command
CMD_SET_PAGE        = 0x01  # "Set Page" Command
CMD_ERASE_PAGE      = 0x02  # "Erase Page" Command
CMD_WRITE_PAGE      = 0x03  # "Write Page" Command
CMD_CRC_PAGE        = 0x04  # "CRC on Page" Command
CMD_SW_RESET        = 0x05  # "Device Reset" Command (Software Reset)
CMD_SET_FLASH_KEYS  = 0x06  # "Set Flash Write/Erase Key Codes" Command
CMD_WRITE_SIGNATURE = 0x07  # "Write Signature to Flash" Command

## BL FW <-> SW Protocol Constants
COMMAND_OK           = 0x00
COMMAND_FAILED       = 0x01
UNKNOWN_COMMAND      = 0x02
SIGNATURE_NOT_ERASED = 0x03
FLASH_KEYS_NOT_SET   = 0x04

## Flash Key Codes valid for 'F32x/'F34x devices
## (to unlock flash writes and erases)
## Note: The flash key codes are sent to the BL FW by the BL SW during the
## bootload operation. So, the BL FW does not need access to these macro 
## definitions directly.
FLASH_KEY0	= 0xA5
FLASH_KEY1	= 0xF1

## Device Codes and Descriptions
NUM_DEVICECODES	= 0x04

MCU_C8051F320_1	  = 0x81
MCU_C8051F326_7   = 0x82
MCU_C8051F34X_32K = 0x83
MCU_C8051F34X_64K = 0x84

MCU_DESC_01 = "C8051F320/1 with 16k Flash"
MCU_DESC_02 = "C8051F326/7 with 16k Flash"
MCU_DESC_03 = "C8051F34x with 32k Flash"
MCU_DESC_04 = "C8051F34x with 64k Flash"

APP_END_PAGE_01 = 0x1D  # Last application page  (page 29)
APP_END_PAGE_02 = 0x1D  # Last application page  (page 29)
APP_END_PAGE_03 = 0x3E  # Last application page  (page 62)
APP_END_PAGE_04 = 0x7C  # Last application page  (page 124)

APP_END_PAGE = APP_END_PAGE_01 # fuerzo F320/1 - F326/7
MCU_DESC = MCU_DESC_01         # fuerzo F320/1
DEV_CODE = MCU_C8051F320_1     # fuerzo F320/1

## Changes to APP_START_PAGE should be mirrored in:
## BL FW's STARTUP.A51 (INTVEC_TABLE)
APP_START_PAGE      = 0x09  # First application page (page 09)
PAGE_SIZE           = 0x200 # Pages are 512 bytes long
APP_START_ADDR      = APP_START_PAGE*PAGE_SIZE

## Max memory size
## Set this to the maximum value of 63kB (for 'F340) because this needs to be 
## known at compile-time. An array of this size is allocated as "m_Memory" in 
## CUSBBootloaderDlg:public CDialog (USBBootloaderDlg.h)
MEMORY_SIZE     = 63*1024

## Location and value of the Validation Signature (16-bit value)
## Any changes to these should be reflected in the PC BL Application
APP_FW_VER_ADDR = ((APP_END_PAGE+1) * PAGE_SIZE) - 4
SIGNATURE_ADDR  = ((APP_END_PAGE+1) * PAGE_SIZE) - 2
REF_SIGNATURE   = 0x3DC2 # Reference Validation Signature (for comparison)

## Device Info Block Structure
##typedef struct DEVICE_INFO_BLOCK
##{
##   CString SerialString;  // Not sent by device in response to CMD_GET_DEVICE_INFO
##   BYTE	BL_FW_ver_high;
##   BYTE	BL_FW_ver_low;
##   BYTE	USBX_FWLib_ver_high;
##   BYTE	USBX_FWLib_ver_low;
##   BYTE  App_FW_ver_high;
##   BYTE  App_FW_ver_low;
##   UINT	signature;
##   BYTE	devCode;
##} DEVICE_INFO_BLOCK;
class DEVICE_INFO_BLOCK(c.Structure):
    _fields_=[("SerialString",c.c_wchar),
              ("BL_FW_ver_high",c.c_byte),
              ("BL_FW_ver_low",c.c_byte),
              ("USBX_FWLib_ver_high",c.c_byte),
              ("USBX_FWLib_ver_low",c.c_byte),
              ("App_FW_ver_high",c.c_byte),
              ("App_FW_ver_low",c.c_byte),
              ("signature",c.c_uint32),
              ("devCode",c.c_byte)]
class BYTE(c.c_byte):
    pass

## The length of the block returned by the BL FW to the BL SW in response to
## the CMD_GET_DEVICE_INFO command; This excludes the CString in the above
## structure.
DEVICE_INFO_BLOCK_RET_LENGTH = 9

## resultados posibles de la API
api_res={  0x00: 'SI_SUCCESS',
           0xFF: 'SI_DEVICE_NOT_FOUND',
           0x01: 'SI_INVALID_HANDLE',
           0x02: 'SI_READ_ERROR',
           0x03: 'SI_RX_QUEUE_NOT_READY',
           0x04: 'SI_WRITE_ERROR',
           0x05: 'SI_RESET_ERROR',
           0x06: 'SI_INVALID_PARAMETER',
           0x07: 'SI_INVALID_REQUEST_LENGTH',
           0x08: 'SI_DEVICE_IO_FAILED',
           0x09: 'SI_INVALID_BAUDRATE',
           0x0A: 'SI_FUNCTION_NOT_SUPPORTED',
           0x0B: 'SI_GLOBAL_DATA_ERROR',
           0x0C: 'SI_SYSTEM_ERROR_CODE',
           0x0D: 'SI_READ_TIMED_OUT',
           0x0E: 'SI_WRITE_TIMED_OUT',
           0x0F: 'SI_IO_PENDING'}

## flags de SI_GetProductString()
dev_str={  'SI_RETURN_SERIAL_NUMBER':  0x00,
           'SI_RETURN_DESCRIPTION':    0x01,
           'SI_RETURN_LINK_NAME':      0x02,
           'SI_RETURN_VID':            0x03,
           'SI_RETURN_PID':            0x04}

# RX Queue status flags
queue_status = {
            0x00:   'SI_RX_EMPTY',  ## or SI_RX_NO_OVERRUN
            0x01:   'SI_RX_OVERRUN',
            0x02:   'SI_RX_READY'}
